package com.basic.system.service.impl;

import com.basic.common.constant.CommonDsConstant;
import com.basic.common.exception.business.DataException;
import com.basic.common.result.Errors;
import com.basic.common.result.WebResult;
import com.basic.system.controller.req.AddSysDeptDto;
import com.basic.system.controller.req.UpdateSysDeptDto;
import com.basic.system.controller.res.SysDeptRes;
import com.basic.system.controller.res.SysDeptVo;
import com.basic.system.dao.mapper.SysDeptExMapper;
import com.basic.system.dao.mapper.SysDeptMapper;
import com.basic.system.dao.model.SysDept;
import com.basic.system.dao.model.SysDeptExample;
import com.basic.system.service.SysDeptService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


@Service
public class SysDeptServiceImpl implements SysDeptService {
    //平级上方
    private static final String levelUp = "levelUp";
    //平级下方
    private static final String levelDown = "levelDown";
    //下级
    private static final String Down = "down";

//    private static final String Horizon = "horizon";

    //根节点
    private static final Long HEAD = 0L;

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysDeptExMapper sysDeptExMapper;

    /**
     * 存入数据库中的毫秒值清空
     * @return 当前时间
     */
    public Date getTimeNow() {
        Date now = new Date();
        // 将毫秒部分清零
        now.setTime(now.getTime() / 1000 * 1000);
        return now;
    }

    /**
     * 添加部门信息
     * @param addSysDeptDto 添加部门信息类
     * @return WebResult
     */
    @Override
    public WebResult addSysDept(AddSysDeptDto addSysDeptDto) {
        //查询上传的类型
        String type = addSysDeptDto.getType();
        //判断是否为平级下方
        if (type.equals(levelDown)) {
            //查询数据库 排序大于传来的排序的最小值，查询条件为父id
            Short min = sysDeptExMapper.selectMinOrderNum(addSysDeptDto.getOrderNum(), addSysDeptDto.getParentId());
            if (min == null) {
                //数据不存在最小值，代表传来的排序为父id中的最大排序，将排序加1赋值给添加的部门
                addSysDeptDto.setOrderNum((short) (addSysDeptDto.getOrderNum() + 1));
            } else {
                addSysDeptDto.setOrderNum(min);
            }
        }
        //创建部门对象
        SysDept sysDept = new SysDept();
        //进行对象拷贝
        BeanUtils.copyProperties(addSysDeptDto, sysDept);
        //通过父id查询部门数据
//        if (sysDept.getParentId() != 0) {
        SysDept sysDeptParent = sysDeptMapper.selectByPrimaryKey(addSysDeptDto.getParentId());

        //设置创建时间
        sysDept.setCreateBy(addSysDeptDto.getCreateBy());
        sysDept.setCreateTime(getTimeNow());
        sysDept.setUpdateTime(getTimeNow());
        //查询父级的祖级数据
        String ancestors = sysDeptParent.getAncestors();
        //与父id进行拼接
        String newAncestors = ancestors + "," + addSysDeptDto.getParentId();
        //设置祖级数据
        sysDept.setAncestors(newAncestors);
        /*} else {
            sysDept.setAncestors(0+"");
        }*/

        SysDeptExample sysDeptExample = new SysDeptExample();
        SysDeptExample.Criteria criteria = sysDeptExample.createCriteria();
        //设置查询的条件
        criteria.andIsEnabledEqualTo(CommonDsConstant.IS_ENABLED);
        //设置条件为父id等于传来的父id
        criteria.andParentIdEqualTo(addSysDeptDto.getParentId());
        //判断类型是否是下级
        if (!type.equals(Down)) {
            //不是下级查询出所有的大于排序的数据
            criteria.andOrderNumGreaterThanOrEqualTo(Short.valueOf(addSysDeptDto.getOrderNum().toString()));
            //获取查询数据的集合
            List<SysDept> sysDepts = sysDeptMapper.selectByExample(sysDeptExample);

            if (!CollectionUtils.isEmpty(sysDepts)) {
                //将排序加1
                sysDeptExMapper.AddOrderNum(sysDepts);
            }
        } else {
            //降级，查询出父id中的最大排序
            int max = sysDeptExMapper.selectMaxOrderNum(addSysDeptDto.getParentId());
            //将排序加1
            Short orderNum = (short) (max + 1);
            //设置排序
            sysDept.setOrderNum(orderNum);
        }

  /*   //未进行层级选择
        if (type.equals(Horizon)){
            criteria.andOrderNumGreaterThan(Short.valueOf(addSysDeptDto.getOrderNum().toString()));
            List<SysDept> deptList = sysDeptMapper.selectByExample(sysDeptExample);
            sysDeptExMapper.AddOrderNum(deptList);
        }*/

        //添加数据
        int i = sysDeptMapper.insertSelective(sysDept);
        if (i == 0) {
            return WebResult.fail(Errors.SYSTEM_INSERT_ERROR);
        }
        return WebResult.success("添加成功");
    }

    /**
     * 修改部门信息
     * @param updateSysDeptDto 修改部门实体类
     * @return WebResult
     */
    @Transactional
    @Override
    public WebResult updateSysDept(UpdateSysDeptDto updateSysDeptDto) {
        //创建对象
        SysDept sysDept = new SysDept();
        //判断是否为根节点
        if (updateSysDeptDto.getParentId().equals(HEAD)) {
            sysDept.setDeptId(updateSysDeptDto.getDeptId());
            sysDept.setDeptName(updateSysDeptDto.getDeptName());
            sysDeptMapper.updateByPrimaryKeySelective(sysDept);
            return WebResult.success();
        }
        //进行部门名称修改并返回
        //updateSysDeptDto的数据拷贝到sysDept中
        BeanUtils.copyProperties(updateSysDeptDto, sysDept);
        //设置更新人
        sysDept.setUpdateBy(updateSysDeptDto.getUpdateBy());
        //设置更新时间
        sysDept.setUpdateTime(getTimeNow());
        //获取祖级列表
        String ancestors = updateSysDeptDto.getAncestorsParent();
        //设置更新后的祖级列表
        String newAncestors = ancestors + "," + updateSysDeptDto.getParentId();

        //查询排序的最大值
        int max = sysDeptExMapper.selectMaxOrderNum(updateSysDeptDto.getParentId());
        //将排序加1
        short orderBy = (short) (max + 1);
        //设置祖级
        sysDept.setAncestors(newAncestors);
        //设置排序
        sysDept.setOrderNum(orderBy);
        //通过主键修改数据
        int i = sysDeptMapper.updateByPrimaryKeySelective(sysDept);
        //使用递归修改子集的祖级
        updateSysDeptAncestors(updateSysDeptDto.getDeptId(), newAncestors);
        if (i == 0) {
            return WebResult.fail(Errors.SYSTEM_UPDATE_ERROR);
        }
        return WebResult.success();

    }

    /**
     * 查询所有信息
     * @param sysDept 查询条件
     * @return WebResult
     */
    @Override
    public List<SysDeptVo> selectAll(SysDept sysDept) {
        SysDeptExample sysDeptExample = new SysDeptExample();
        SysDeptExample.Criteria criteria = sysDeptExample.createCriteria();
        criteria.andIsEnabledEqualTo(CommonDsConstant.IS_ENABLED);
        criteria.andDeptTypeEqualTo(sysDept.getDeptType());

        // 查询所有根节点（父ID为0）
        criteria.andParentIdEqualTo(0L);
        List<SysDept> sysDepts = sysDeptMapper.selectByExample(sysDeptExample);

        if (CollectionUtils.isEmpty(sysDepts)) {
            return null;
        }

        // 查询所有部门
        List<SysDeptVo> sysDeptVos = sysDeptExMapper.selectAll(sysDept.getDeptType());

        // 将查询的集合转换为map类型
        Map<Long, SysDeptVo> map = sysDeptVos.stream().collect(Collectors.toMap(SysDept::getDeptId, item -> item));

        List<SysDeptVo> sysDeptList = new ArrayList<>();

        // 遍历所有根节点，构建树形结构
        for (SysDept rootDept : sysDepts) {
            SysDeptVo rootDeptVo = map.get(rootDept.getDeptId());
            if (rootDeptVo != null) {
                sysDeptList.add(rootDeptVo); // 添加根节点到结果列表
                // 递归添加子节点
                addChildren(rootDeptVo, map);
            }
        }

        // 返回结果列表
        return sysDeptList;
    }

    // 递归方法，添加子节点
    private void addChildren(SysDeptVo parentDeptVo, Map<Long, SysDeptVo> map) {
        List<SysDeptVo> children = map.values().stream()
                .filter(item -> item.getParentId().equals(parentDeptVo.getDeptId()))
                .collect(Collectors.toList());

        if (!children.isEmpty()) {
            if (parentDeptVo.getSysDeptVos() == null) {
                parentDeptVo.setSysDeptVos(new ArrayList<>());
            }
            parentDeptVo.getSysDeptVos().addAll(children);

            // 递归调用，为每个子节点添加其子节点
            for (SysDeptVo child : children) {
                addChildren(child, map);
            }
        }
    }

    /**
     * 批量删除（假删）
     * @param deptIds 部门id集合
     * @return WebResult
     */
    @Override
    public WebResult delete(List<Long> deptIds) {
        int count = sysDeptExMapper.updateByIds(deptIds);
        if (count == 0) {
            return WebResult.fail(Errors.SYSTEM_DELETE_ERROR);
        }
        return WebResult.success();

    }

    /**
     * 逻辑删除
     * @param deptId 部门id
     * @return WebResult
     */
    @Override
    public WebResult markDeleted(Long deptId) {
        int row = sysDeptExMapper.markDeleted(deptId);

        if (row == 0) {
            throw new DataException("删除数据失败");
        }
        return WebResult.success();
    }

    /**
     * 根据部门主键进行查询
     * @param deptId 主键
     * @return WebResult
     */
    @Override
    public WebResult selectByPrimaryKey(Long deptId) {
        if (deptId == null) {
            return WebResult.fail(Errors.SYSTEM_DATA_ERROR);
        }

        SysDeptExample sysDeptExample = new SysDeptExample();
        SysDeptExample.Criteria criteria = sysDeptExample.createCriteria();
        criteria.andIsEnabledEqualTo(CommonDsConstant.IS_ENABLED);
        criteria.andDeptIdEqualTo(deptId);
        List<SysDept> sysDepts = sysDeptMapper.selectByExample(sysDeptExample);
        if (sysDepts.isEmpty()) {
            return WebResult.fail(Errors.SYSTEM_DATA_ERROR);
        }
        return WebResult.success(sysDepts.get(0));
    }


    /**
     * 根据部门名称模糊查询
     * @param sysDept 部门
     * @return WebResult
     */
    @Override
    public WebResult selectByDeptName(SysDept sysDept) {
        SysDeptExample sysDeptExample = new SysDeptExample();
        SysDeptExample.Criteria criteria = sysDeptExample.createCriteria();
        //进行模糊查询
        criteria.andDeptNameLike("%" + sysDept.getDeptName() + "%");
        //匹配systemid
        criteria.andSystemIdEqualTo(sysDept.getSystemId());
        criteria.andIsEnabledEqualTo(CommonDsConstant.IS_ENABLED);
        criteria.andDeptTypeEqualTo(sysDept.getDeptType());
        List<SysDept> sysDepts = sysDeptMapper.selectByExample(sysDeptExample);
        return WebResult.success(sysDepts);
    }

    /**
     * 用于递归修改祖级id以及父id
     * @param parentId  父id
     * @param ancestors 祖级id
     */
    private void updateSysDeptAncestors(long parentId, String ancestors) {
        SysDeptExample sysDeptExample = new SysDeptExample();
        SysDeptExample.Criteria criteria = sysDeptExample.createCriteria();
        criteria.andParentIdEqualTo(parentId);
        criteria.andIsEnabledEqualTo(CommonDsConstant.IS_ENABLED);
        //拼接新的祖级列表的id
        String newAncestors = ancestors + "," + parentId;
        //查询所有符合父id的部门信息
        List<SysDept> sysDepts = sysDeptMapper.selectByExample(sysDeptExample);
        //如果为空无需修改
        if (sysDepts == null) {
            return;
        }
        //不为空遍历所有
        for (SysDept sysDept : sysDepts) {
            SysDept sysDept1 = new SysDept();
            //获取部门id
            sysDept1.setDeptId(sysDept.getDeptId());
            //将更新后的祖级列表放进去
            sysDept1.setAncestors(newAncestors);
            //进行修改
            sysDeptMapper.updateByPrimaryKeySelective(sysDept1);
            //递归修改
            updateSysDeptAncestors(sysDept.getDeptId(), newAncestors);
        }
    }

    /**
     * 通过父id进行查询
     * @param sysDept 部门
     * @return WebResult
     */
    @Override
    public WebResult selectAllByParam(SysDept sysDept) {
        SysDept newSysDept = sysDeptMapper.selectByPrimaryKey(sysDept.getParentId());
        SysDeptExample example = new SysDeptExample();
        SysDeptExample.Criteria criteria = example.createCriteria();
  /*      if (sysDept.getParentId() != null) {
            criteria.andDeptIdEqualTo(sysDept.getParentId());
        }*/
        criteria.andDeptTypeEqualTo(sysDept.getDeptType());
        //拿着获取到的父id   匹配所有均为相同的parentId
        //传deptId则会 匹配所有的相同的父id也就是同级所有
        //传parentId 匹配到的是所有的上级
        criteria.andParentIdEqualTo(newSysDept.getParentId());
        criteria.andIsEnabledEqualTo(CommonDsConstant.IS_ENABLED);
        List<SysDept> sysDepts = sysDeptMapper.selectByExample(example);
        return WebResult.success(sysDepts);
    }

    /**
     * 通过部门id查询所有同级以及子级数据
     * @param sysDept 部门
     * @return WebResult
     */
    @Override
    public List<SysDept> selByDept(SysDept sysDept) {
        if (sysDept.getDeptId() == null) {
            throw new DataException("部门id不能为空");
        }
        if (sysDept.getDeptType() == null) {
            throw new DataException("部门类型不能为空");
        }
        SysDeptExample sysDeptExample = new SysDeptExample();
        SysDeptExample.Criteria criteria = sysDeptExample.createCriteria();
        criteria.andIsEnabledEqualTo(CommonDsConstant.IS_ENABLED);

        Long deptId = sysDept.getDeptId();
        // 根据部门ID查询部门信息
        SysDept dept = sysDeptMapper.selectByPrimaryKey(deptId);
        // 设置父部门ID
        sysDept.setParentId(dept.getParentId());
        // 根据部门信息查询子部门列表
        List<SysDept> deptList = sysDeptExMapper.selByDept(sysDept);
        // 构建部门树
        return buildTree(deptList, dept.getParentId());
    }

    /**
     * 根据deptid查询下方所有的数据
     * @param sysDept 实体类
     * @return List<SysDeptRes>
     */
    @Override
    public List<SysDept> selSysDeptSubdata(SysDept sysDept) {
        if (sysDept.getDeptId() == null) {
            throw new DataException("部门id不能为空");
        }
        if (sysDept.getDeptType() == null) {
            throw new DataException("部门类型不能为空");
        }
        List<SysDept> sysDeptRes = sysDeptExMapper.selSysDeptSubdata(sysDept);
        if (CollectionUtils.isEmpty(sysDeptRes)) {
            return Collections.emptyList();
        }
        Long deptId = sysDept.getDeptId();
        SysDept dept = sysDeptMapper.selectByPrimaryKey(deptId);

        return buildTree(sysDeptRes, dept.getParentId());
    }

    /**
     * 只查询下级数据-仅一层
     * @param sysDept 实体类
     * @return List<SysDept>
     */
    @Override
    public List<SysDept> selSDsubordinate(SysDept sysDept) {
        if(sysDept.getDeptId() == null) {
            throw new DataException("部门id不能为空");
        }
        if(sysDept.getDeptType() == null) {
            throw new DataException("部门类型不能为空");
        }
        SysDeptExample example = new SysDeptExample();
        SysDeptExample.Criteria criteria = example.createCriteria();
        criteria.andParentIdEqualTo(sysDept.getDeptId());
        criteria.andDeptTypeEqualTo(sysDept.getDeptType());
        criteria.andIsEnabledEqualTo(CommonDsConstant.IS_ENABLED);
        List<SysDept> sysDeptList = sysDeptMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(sysDeptList)) {
            return Collections.emptyList();
        }
        return sysDeptList;
    }

    @Override
    public List<SysDeptRes> selectAllRes(SysDept sysDept) {
        SysDeptExample sysDeptExample = new SysDeptExample();
        SysDeptExample.Criteria criteria = sysDeptExample.createCriteria();
        criteria.andIsEnabledEqualTo(CommonDsConstant.IS_ENABLED);
        criteria.andDeptTypeEqualTo(sysDept.getDeptType());
        //根节点的父id为0
        criteria.andParentIdEqualTo(0L);
        List<SysDept> sysDepts = sysDeptMapper.selectByExample(sysDeptExample);
        if (CollectionUtils.isEmpty(sysDepts)) {
            return null;
        }
        SysDept sysDeptNew = sysDepts.get(0);
        //查询所有
        List<SysDeptRes> sysDeptVos = sysDeptExMapper.selectAllRes(sysDeptNew.getDeptId(), sysDept.getDeptType());
        //将查询的集合转换为map类型
        Map<Long, SysDeptRes> map = sysDeptVos.stream().collect(Collectors.toMap(item -> item.getValue(), item -> item));
        List<SysDeptRes> sysDeptList = new ArrayList<>();
        //将第一个父节点进行添加
        sysDeptList.add(map.get(sysDeptNew.getDeptId()));
        sysDeptVos.forEach(item -> {
            //查询所有父类为传的id
            if (item.getParentId().equals(sysDeptNew.getDeptId())) {
                SysDeptRes sysDeptVo = map.get(item.getValue());
                SysDeptRes sysDeptVo1 = sysDeptList.get(0);
                if (CollectionUtils.isEmpty(sysDeptVo1.getChildren())) {
                    sysDeptVo1.setChildren(new ArrayList<>());
                }
                sysDeptVo1.getChildren().add(sysDeptVo);

            } else {
                //查询所对应的父类id
                SysDeptRes sysDeptVo = map.get(item.getParentId());
                if (sysDeptVo != null) {
                    //查询sysDeptVo.getSysDeptVos()是否为空 ,为空创建对象
                    if (sysDeptVo.getChildren() == null || sysDeptVo.getChildren().isEmpty()) {
                        sysDeptVo.setChildren(new ArrayList<>());
                    }
                    //添加到集合
                    sysDeptVo.getChildren().add(item);
                }
            }
        });
        //返回集合
        return sysDeptList;
    }

    /**
     * 数据构建为树形
     * @param depts 部门实体
     * @param parentId 父id
     * @return List<SysDept>
     */
    private List<SysDept> buildTree(List<SysDept> depts, Long parentId) {
        // 创建一个LinkedHashMap来存储depts中的元素
        Map<Long, SysDept> map = new LinkedHashMap<>();
        // 遍历depts中的元素，将其添加到LinkedHashMap中
        for (SysDept dept : depts) {
            map.put(dept.getDeptId(), dept);
        }

        // 创建一个ArrayList来存储depts中的元素
        List<SysDept> tree = new ArrayList<>();
        // 遍历depts中的元素，将其添加到ArrayList中
        for (SysDept dept : depts) {
            // 如果dept的parentId为null或者等于parentId，将其添加到ArrayList中
            if (dept.getParentId() == null ||
                    Objects.equals(dept.getParentId(), parentId)) {
                tree.add(dept);
                // 如果dept的parentId不为null且不等于parentId，且LinkedHashMap中包含parentId，将其添加到LinkedHashMap中
            } else if (map.containsKey(dept.getParentId())) {
                SysDept parent = map.get(dept.getParentId());
                // 如果parent的children为空，将其添加到ArrayList中
                if (CollectionUtils.isEmpty(parent.getChildren())) {
                    parent.setChildren(new ArrayList<>());
                }
                // 将dept添加到parent的children中
                parent.getChildren().add(dept);
                // 如果dept的parentId不为null且不等于parentId，且LinkedHashMap中不包含parentId，将其添加到LinkedHashMap中
            } else {
                if (!map.containsKey(dept.getDeptId())) {
                    SysDept newNode = new SysDept();
                    // 将其children设置为一个ArrayList
                    newNode.setChildren(new ArrayList<>());
                    // 将其deptId设置为dept的deptId
                    newNode.setDeptId(dept.getDeptId());
                    // 将其name设置为dept的name
                    newNode.setName(dept.getDeptName());

                    // 将newNode添加到ArrayList中
                    tree.add(newNode);
                }
            }
        }

        // 返回ArrayList
        return tree;
    }

}

